﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Windows;
using DataGenerator.DefaultSets;
using Dispatcher.Extensions;
using Dispatcher.Helpers;
using Dispatcher.ViewModels.Base;
using Dispatcher.Views;
using Repository;

namespace Dispatcher.ViewModels
{
    /// <summary>
    /// Event Edit View Model.
    /// </summary>
    public class EventEditViewModel : ViewModelBase
    {
        /// <summary>
        /// Person Group Type Set.
        /// </summary>
        private readonly PersonGroupTypeSet _personGroupTypeSet;

        /// <summary>
        /// Event Group Type Set.
        /// </summary>
        private readonly EventGroupTypeSet _eventGroupTypeSet;

        /// <summary>
        /// Initializes a new instance of the <see cref="EventEditViewModel"/> class.
        /// </summary>
        /// <param name="modelContainer">The model container.</param>
        public EventEditViewModel(ModelContainer modelContainer)
        {
            ModelContainer = modelContainer;
            var eventGroupTypeSet = new EventGroupTypeSet(ModelContainer.EventGroupTypeSet);

            ClassTypes =
                ModelContainer.EventGroupSet.
                Where(g => g.EventGroupType.Id == eventGroupTypeSet.Class.Id).ToList();
            ClassTypes.Sort((x, y) => StaticObjects.DefaultStringComparer.Compare(x.Name, y.Name));

            Weeks =
                ModelContainer.EventGroupSet.
                Where(g => g.EventGroupType.Id == eventGroupTypeSet.Periodic.Id).ToList();

            OrganizePersons = ModelContainer.PersonSet.ToList();
            OrganizePersons.Sort((x, y) => StaticObjects.DefaultStringComparer.Compare(x.FirstName, y.FirstName));

            SelectedWeeks = new List<EventGroup>();

            _personGroupTypeSet = new PersonGroupTypeSet(modelContainer.PersonGroupTypeSet);
            _eventGroupTypeSet = new EventGroupTypeSet(modelContainer.EventGroupTypeSet);

            var roleSet = new RoleSet(modelContainer.RoleSet);
            if (MainWindow.CurrentUser.Role.Name == roleSet.User.Name)
            {
                SelectedOrganizePerson = MainWindow.CurrentUser.Person;
                if (SelectedOrganizePerson == null)
                {
                    MessageBox.Show("Ваш логин не привязан к конкретному человеку. " + Environment.NewLine +
                                    "Обратитесь к администратору.");
                }
            }

            PeriodStart = DateTime.Parse(ConfigurationManager.AppSettings["PeriodStart"]);
            PeriodEnd = DateTime.Parse(ConfigurationManager.AppSettings["PeriodEnd"]);
            SingleDate = DateTime.Now.Date;
        }

        public ModelContainer ModelContainer { get; set; }

        public bool IsSingle
        {
            get
            {
                return Get(() => IsSingle);
            }
            set
            {
                Set(() => IsSingle, value);
            }
        }

        public DateTime SingleDate { get; set; }

        public Place Place { get; set; }

        public string Name { get; set; }

        public TimeSpan StartTime { get; set; }

        public TimeSpan EndTime { get; set; }

        public DateTime PeriodStart
        {
            get
            {
                return Get(() => PeriodStart);
            }
            set
            {
                Set(() => PeriodStart, value);
            }
        }

        public DateTime PeriodEnd
        {
            get
            {
                return Get(() => PeriodEnd);
            }
            set
            {
                Set(() => PeriodEnd, value);
            }
        }

        public List<EventGroup> ClassTypes { get; set; }

        public List<EventGroup> Weeks { get; set; }

        public List<Person> OrganizePersons { get; set; }

        public List<EventGroup> SelectedWeeks { get; set; } 

        public EventGroup SelectedClassType { get; set; }

        public Person SelectedOrganizePerson { get; set; }

        public bool Validate()
        {
            if (!IsSingle && SelectedWeeks.Count == 0)
            {
                MessageBox.Show("Выберите недели, пожалуйста.");
                return false;
            }

            if (SelectedOrganizePerson == null)
            {
                MessageBox.Show("Выберите организатора, пожалуйста.");
                return false;
            }

            if (SelectedClassType == null)
            {
                MessageBox.Show("Выберите тип занятия, пожалуйста.");
                return false;
            }

            return true;
        }

        public void Save()
        {
            if (Place == null)
            {
                throw new Exception("Place not seted");
            }

            if (!IsSingle && SelectedWeeks.Count == 0)
            {
                PeriodEnd = PeriodStart;
            }

            var eventPeriodGroup = new EventGroup
                                       {
                                           Name =
                                               "Period: " + PeriodStart.ToShortDateString() +
                                               PeriodEnd.ToShortDateString(),
                                               EventGroupType = _eventGroupTypeSet.GroupByPeriod, 
                                       };

            var start = PeriodStart;
            var end = PeriodEnd;

            if (IsSingle)
            {
                start = SingleDate;
                end = SingleDate;
            }

            for (var date = start; date <= end; date = date.AddDays(7))
            {
                DateTime yearStart;
                var firstWeek = ConfigurationManager.AppSettings["FirstWeek"];
                if (!DateTime.TryParse(firstWeek, out yearStart))
                {
                    yearStart = new DateTime(date.Year, 1, 1);
                }
                
                var dayOfYear = (date - yearStart).Days;
                var weekNumber = dayOfYear/7;
                var week = weekNumber%4 + 1;

                if (!IsSingle && SelectedWeeks.Count > 0 && SelectedWeeks.All(g => g.Name != week + "-я неделя"))
                {
                    continue;
                }

                var from = date + StartTime;
                var to = date + EndTime;
                var isBusy = ModelContainer.EventSet.Where(
                    e =>
                    (from == e.StartTime && e.EndTime == to) ||
                    (from < e.StartTime && e.StartTime < to) ||
                    (from < e.EndTime && e.EndTime < to)).Any(e => e.Place.Id == Place.Id);

                if (isBusy)
                {
                    continue;
                }

                var ev = ModelContainer.EventSet.CreateObject();
                ev.Place = Place;
                ev.EventGroup.Add(SelectedClassType);
                if(!IsSingle)
                {
                    ev.EventGroup.Add(eventPeriodGroup);
                }

                ev.Name = Name;
                ev.StartTime = from;
                ev.EndTime = to;
                ev.OrganizePersonGroup =
                    ModelContainer.PersonGroupSet.FirstOrDefault(
                        g =>
                        g.Person.Any(p=>p.Id == SelectedOrganizePerson.Id) &&
                        g.PersonGroupType.Id == _personGroupTypeSet.SinglePerson.Id);
                ev.EventGroup.AddRange(SelectedWeeks);
            }

            ModelContainer.HasChanges();
            ModelContainer.SaveChanges();

           // ConfigurationManager.AppSettings.Set("PeriodStart", PeriodStart.ToString(CultureInfo.InvariantCulture));
           // ConfigurationManager.AppSettings.Set("PeriodEnd", PeriodEnd.ToString(CultureInfo.InvariantCulture));
        }
    }
}
